package GinRouter

import (
	"context"
	"gin-service/lib/GormSrv"
	"gin-service/lib/MongoSrv"
	"gin-service/utils"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"net/http"
	"strings"
)

type RespCallback func(ctx *gin.Context)

type Router interface {
	GetEngine() *gin.Engine

	/*
	 * 取得GinEngine实例
	 * 取得GinEngine Group实例
	 */
	InitRouter()

	/*
	 * Get请求
	 */
	Get(relativePath string, respCallback RespCallback)

	/*
	 * Post请求
	 */
	Post(relativePath string, respCallback RespCallback)

	/*
	 * Put请求
	 */
	Put(relativePath string, respCallback RespCallback)

	/*
	 * Delete请求
	 */
	Delete(relativePath string, respCallback RespCallback)
}

func ThrowError(err error)  {
	if err != nil {
		panic(err.Error())
	}
}

func ThrowErrorReturn(res interface{}, err error) interface{} {
	if err != nil {
		panic(err.Error())
	}

	return res
}

func ErrorHandler(ctx *gin.Context) {
	if err := recover(); err != nil {
		requestUri := ctx.Request.RequestURI
		pathArray := strings.Split(requestUri, "/")

		respCode := http.StatusBadRequest
		if pathArray[1] == "erc" {
			respCode = http.StatusOK
		}

		ctx.JSON(respCode, gin.H{
			"status": 1,
			"message": err,
		})
	}
}

var ctx = context.Background()

func GormQuery(ginCtx *gin.Context, tableName string, selectColumn []string, resultData map[string]interface{}, filterFunc func(subQuery *gorm.DB) *gorm.DB) *gorm.DB {
	query := GormSrv.GDB().Table(tableName).Select(selectColumn)

	offset := utils.STI(ginCtx.DefaultQuery("offset", "0"))
	limit := utils.STI(ginCtx.DefaultQuery("limit", "-1"))
	query = query.Offset(offset).Limit(limit)

	pagingQuery := ginCtx.Query("paging_query")
	if utils.STB(pagingQuery) {
		var count int
		query.Count(&count)
		resultData["count"] = count
	}

	if filterFunc != nil {
		query = filterFunc(query)
	}

	return query
}

func MongoQuery(ginCtx *gin.Context, tableName string, filter bson.M, sort bson.M) map[string]interface{} {
	resultData := map[string]interface{}{}

	collection := MongoSrv.Mongo().DB.Collection(tableName)

	findOptions := options.Find()
	if sort != nil {
		findOptions.SetSort(sort)
	}

	offset := utils.STI64(ginCtx.DefaultQuery("offset", "0"))
	findOptions.SetSkip(offset)

	limit := utils.STI64(ginCtx.DefaultQuery("limit", "0"))
	findOptions.SetLimit(limit)

	pagingQuery := ginCtx.Query("paging_query")
	if utils.STB(pagingQuery) {
		res := ThrowErrorReturn(collection.CountDocuments(ctx, filter))
		count := res.(int64)
		resultData["total"] = count
	}

	res := ThrowErrorReturn(collection.Find(ctx, filter, findOptions))
	cursor := res.(*mongo.Cursor)
	defer cursor.Close(ctx)

	var dataList = make([]bson.M, 0)
	ThrowError(cursor.All(ctx, &dataList))

	resultData["rows"] = dataList

	return resultData
}
